package com.dj.myapp.router;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;

import com.dj.myapp.annotation.CombinationUri;
import com.dj.myapp.annotation.InjectParam;
import com.dj.myapp.annotation.RouterParam;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public final class Router {

    private static Router mRouter;
    private Router(){
    }

//    public Router getInstance(Context context) {
//        if(null==mRouter){
//            synchronized (Router.class){
//                if (null==mRouter){
//                    mRouter=new Router();
//                    mContext=context;
//                }
//            }
//        }
//        return mRouter;
//    }

    public static Router getInstance() {
        if(null==mRouter){
            mRouter=new Router();
        }
        return mRouter;
    }


    public void creatData(Context context, RouterParam routerParam){

        StringBuilder urlBuilder = new StringBuilder();

        CombinationUri combinationUri=routerParam.getCombinationUri();
        if (combinationUri != null) {
            String scheme = combinationUri.getScheme();
            String host = combinationUri.getHost();
            String port = combinationUri.getPort();
            String path = combinationUri.getPath();

            urlBuilder.append(scheme).append("://").append(host)
                    .append(isEmpty(port) ? "" : ":" + port)
                    .append(isEmpty(path) ? "" : path.startsWith("/") ? path : ("/" + path));
        }

        HashMap<String, String> uriParam=routerParam.getUriParam();
        int position = 0;
        for (String key : uriParam.keySet()) {
            if (!isEmpty(key)) {
                urlBuilder.append(position == 0 ? "?" : "&");
                position++;
                urlBuilder.append(key).append("=").append(uriParam.get(key));
            }
        }

        HashMap<String, Object> intentExtrasParam=routerParam.getIntentExtrasParam();

        performJump(context,urlBuilder.toString(), intentExtrasParam);

    }

    private void performJump(Context context,String routerUri, HashMap<String, Object> serializedParams){

        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(routerUri));
        Bundle bundle = new Bundle();
        for (Map.Entry<String, Object> entry : serializedParams.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();

            if (value instanceof Integer) {
                bundle.putInt(key, Integer.parseInt(value.toString()));
            } else if (value instanceof Long) {
                bundle.putLong(key, Long.parseLong(value.toString()));
            } else if (value instanceof Double) {
                bundle.putDouble(key, Double.parseDouble(value.toString()));
            } else if (value instanceof Short) {
                bundle.putShort(key, Short.parseShort(value.toString()));
            } else if (value instanceof Float) {
                bundle.putFloat(key, Float.parseFloat(value.toString()));
            } else if (value instanceof String) {
                bundle.putString(key, (String) value);
            } else if (value instanceof CharSequence) {
                bundle.putCharSequence(key, (CharSequence) value);
            } else if (value.getClass().isArray()) {
                if (int[].class.isInstance(value)) {
                    bundle.putIntArray(key, (int[]) value);
                } else if (long[].class.isInstance(value)) {
                    bundle.putLongArray(key, (long[]) value);
                } else if (double[].class.isInstance(value)) {
                    bundle.putDoubleArray(key, (double[]) value);
                } else if (short[].class.isInstance(value)) {
                    bundle.putShortArray(key, (short[]) value);
                } else if (float[].class.isInstance(value)) {
                    bundle.putFloatArray(key, (float[]) value);
                } else if (String[].class.isInstance(value)) {
                    bundle.putStringArray(key, (String[]) value);
                } else if (CharSequence[].class.isInstance(value)) {
                    bundle.putCharSequenceArray(key, (CharSequence[]) value);
                }
            } else if (value instanceof ArrayList && !((ArrayList) value).isEmpty()) {
                ArrayList list = (ArrayList) value;
                if (list.get(0) instanceof Integer) {
                    bundle.putIntegerArrayList(key, (ArrayList<Integer>) value);
                } else if (list.get(0) instanceof String) {
                    bundle.putStringArrayList(key, (ArrayList<String>) value);
                } else if (list.get(0) instanceof CharSequence) {
                    bundle.putCharSequenceArrayList(key, (ArrayList<CharSequence>) value);
                }
            }  else if (value instanceof Serializable) {
                bundle.putSerializable(key, (Serializable) value);
            } else {
                throw new IllegalArgumentException("不支持的参数类型！");
            }
        }
        intent.putExtras(bundle);
        PackageManager packageManager = context.getPackageManager();
        List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
        if (!activities.isEmpty()) {
            context.startActivity(intent);
        }

    }

    public HashMap<String,Object> injectData(Intent intent,InjectParam injectParam){
        HashMap<String,Object> data=new HashMap<>();
        Bundle bundle=intent.getExtras();
        if(data!=null){
            String[] inject=injectParam.getInject();
            for(String str:inject){
                Object value=bundle.get(str);
                if(!isEmpty(value)){
                    data.put(str,value);
                }
            }
        }
        Uri uri = intent.getData();
        if (uri !=null ){
            String[] injectUri=injectParam.getInjectUriParam();
            for(String str:injectUri){
                String value=uri.getQueryParameter(str);
                if(!isEmpty(value)){
                    data.put(str,value);
                }
            }
        }
        return data;
    }


    private Boolean isEmpty(Object str){
        return (str==null)||(str.toString().trim()=="");
    }

}
